#include "tools.h"
#include <fcntl.h>
#include <time.h>
#include <stdio.h>

#define BUFSIZE 16

// 基本算法：
// 创建套接字
// 监听，阻塞
// 收到连接，交给子进程处理
// 继续监听

static int 
handle_request(int sockfd) {
    char buf[BUFSIZE];
    int size = -1;

    // 如果设置为阻塞地读取，而且又没有设置超时
    // 那么如果客户端建立连接之后一直不发送数据
    // 这时候服务器的资源就浪费了呀，不能忍受
    // 所以下面设置了间隔1s没有收到就关闭连接

    // 等1s，不发数据就关了
    struct timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    //setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
    
    // 不管客户端发多少数据
    while ( (size=read(sockfd, buf, BUFSIZE)) > 0) {
        if (write(sockfd, buf, size) < 0) {
            error("error writing to socket");
            return -1;
        }
    }

    /*
    // 超时，清空错误然后返回
    if (errno == EAGAIN) {
        errno = 0;
        return 0;
    }
    */

    if (size < 0)
        return -1;
    return 0;
}

int
main(int argc, char** argv){

    if (argc < 2) {
        fprintf(stderr, "Usage: %s <port number>\n", argv[0]);
        exit(-1);
    }

    int sockfd, newsockfd;
    int portNumber = atoi(argv[1]);

    struct in_addr ip_addr;
    ip_addr.s_addr = INADDR_ANY;
    struct sockaddr_in addr = get_sockaddr_in(portNumber, ip_addr);
    socklen_t addrlen = sizeof(addr);

    sockfd = get_server_socket(portNumber, SOCK_STREAM, 32);

    info("listening to port %d", portNumber);
    while ( (newsockfd=accept(sockfd,(struct sockaddr*)&addr, &addrlen)) > 0) {
        // fork之后交给子进程处理
        info("receive connection from %s", inet_ntoa(addr.sin_addr));
        switch( fork() ){
            case 0:
                // child
                if (handle_request(newsockfd) == -1){
                    close(newsockfd);
                    error_exit("", "error occured while handling request");
                }
                close(newsockfd);
                exit(0);
            case -1:
                error_exit("fork", "error forking");
            default:
                // parent
                close(newsockfd);
                break;
        }
    }
}
